home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
C/C++ Interactive Reference Guide
/
C-C++ Interactive Reference Guide.iso
/
c_ref
/
csource5
/
347_01
/
tavlrebl.c
< prev
next >
Wrap
C/C++ Source or Header
|
1991-10-20
|
6KB
|
184 lines
/*:file:version:date: "%n V.%v; %f"
* "TAVLREBL.C V.9; 20-Oct-91,13:38:42"
*
* Module: Rebalance
* Purpose: Rebalance the TAVLtree "a", which is unbalanced by at most
* one leaf. This function may be called by either "tavl_insert"
* or "tavl_delete"; Rebalance is considered to be private to the
* TAVL routines, its prototype is in the header "tavlpriv.h",
* whereas user routine prototypes are in "tavltree.h".
* Assumes balance factors & threads are correct; Returns pointer
* to root of balanced tree; threads & balance factors have been
* corrected if necessary. If the height of the subtree "a"
* decreases by one, tavl_rebalance sets *deltaht to 1, otherwise
* *deltaht is set to 0. If "tavl_rebalance" is called by
* "tavl_insert", *deltaht will always be set to 1 - just by the
* nature of the algorithm. So the function "tavl_insert" does
* not need the information provided by *deltaht; however,
* "tavl_delete" does use this information.
*
* Author: Bert C. Hughes
*
* !!NOTE!! This module must be linked into any program which uses
* the TAVL library functions "tavl_insert" or "tavl_delete"!
* This module is strictly for the use of those functions, and
* is NOT intended to be a "user", or TAVL library, function.
*
* Released to the PUBLIC DOMAIN
* Bert C. Hughes
* 200 N.Saratoga
* St.Paul, MN 55104
* Compuserve 71211,577
*/
/* Debugging "assert"s are in the code to test integrity of the */
/* tree. All assertions should be removed from production versions */
/* of the library by compiling the library with NDEBUG defined. */
/* See the header "assert.h".*/
#include <stdlib.h>
#include <assert.h>
#include "tavltree.h"
#include "tavlpriv.h"
TAVL_nodeptr rebalance_tavl(TAVL_nodeptr a, char *deltaht)
{
TAVL_nodeptr b,c,sub_root; /* sub_root will be the return value, */
/* and the root of the newly rebalanced*/
/* sub-tree */
/* definition(tree-height(X)) : the maximum */
/* path length from node X to a leaf node. */
*deltaht = 0; /* *deltaht is set to 1 if and only if */
/* tree-height(rebalance()) < tree-height(a)*/
if (Is_Head(a) /* Never rebalance the head node! */
|| abs(a->bf) <= 1) /* tree "a" is balanced - nothing more to do */
return(a);
if (a->bf == LEFT+LEFT) {
b = a->Lptr;
if (b->bf != RIGHT) { /* LL rotation */
if (RTHREAD(b)) { /* b->Rptr is a thread to "a" */
assert(b->Rptr == a);
a->Lbit = THREAD; /* change from link to thread */
b->Rbit = LINK; /* change thread to link */
}
else {
a->Lptr = b->Rptr;
b->Rptr = a;
}
*deltaht = b->bf ? 1 : 0;
a->bf = - (b->bf += RIGHT);
sub_root = b;
}
else { /* LR rotation */
*deltaht = 1;
c = b->Rptr;
if (LTHREAD(c)) {
assert(c->Lptr == b);
c->Lbit = LINK;
b->Rbit = THREAD;
}
else {
b->Rptr = c->Lptr;
c->Lptr = b;
}
if (RTHREAD(c)) {
assert(c->Rptr == a);
c->Rbit = LINK;
a->Lptr = c;
a->Lbit = THREAD;
}
else {
a->Lptr = c->Rptr;
c->Rptr = a;
}
switch (c->bf) {
case LEFT: b->bf = 0;
a->bf = RIGHT;
break;
case RIGHT: b->bf = LEFT;
a->bf = 0;
break;
case 0: b->bf = 0;
a->bf = 0;
}
c->bf = 0;
sub_root = c;
}
}
else if (a->bf == RIGHT+RIGHT) {
b = a->Rptr;
if (b->bf != LEFT) { /* RR rotation */
if (LTHREAD(b)) { /* b->Lptr is a thread to "a" */
assert(b->Lptr == a);
a->Rbit = THREAD; /* change from link to thread */
b->Lbit = LINK; /* change thread to link */
}
else {
a->Rptr = b->Lptr;
b->Lptr = a;
}
*deltaht = b->bf ? 1 : 0;
a->bf = - (b->bf += LEFT);
sub_root = b;
}
else { /* RL rotation */
*deltaht = 1;
c = b->Lptr;
if (RTHREAD(c)) {
assert(c->Rptr == b);
c->Rbit = LINK;
b->Lbit = THREAD;
}
else {
b->Lptr = c->Rptr;
c->Rptr = b;
}
if (LTHREAD(c)) {
assert(c->Lptr == a);
c->Lbit = LINK;
a->Rptr = c;
a->Rbit = THREAD;
}
else {
a->Rptr = c->Lptr;
c->Lptr = a;
}
switch (c->bf) {
case RIGHT: b->bf = 0;
a->bf = LEFT;
break;
case LEFT: b->bf = RIGHT;
a->bf = 0;
break;
case 0: b->bf = 0;
a->bf = 0;
}
c->bf = 0;
sub_root = c;
}
}
return sub_root;
}/* end rebalance */